import base64
from datetime import timedelta
from decimal import Decimal, InvalidOperation, getcontext
import json
import os
import random
import string
import time
from django.views.decorators.csrf import csrf_exempt
import requests
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.serialization import load_pem_private_key
from django.db.models import F
import logging
from django.db import transaction
from django.utils.translation import gettext as _
from django.utils.dateparse import parse_datetime
from django.conf import settings
from django.db.models import Prefetch
from rest_framework.views import APIView
from rest_framework import generics, permissions, status, viewsets,filters,serializers
from rest_framework.response import Response
from rest_framework.decorators import action
from rest_framework.permissions import IsAdminUser, IsAuthenticated
from rest_framework.pagination import PageNumberPagination
from django.db.models import Sum
from apps.chefs.models import DjChef
from apps.menu.models import DjDish, DjDishImage
from apps.orders.services.wechat_refund_service import WechatRefundService
from apps.payments.models import DjChefWallet, DjWalletTransaction
from apps.schedules.models import TimeSlot
from config.settings.base import WECHAT_CONFIG
from core.permissions import IsChefOwner
from .models import DjChefOrder, Order, OrderItem, OrderStatusLog
from apps.schedules.models import TimeSlot
from .serializers import ChefServiceOrderItemSerializer, ChefServiceOrderSerializer, DjChefOrderSerializer, DjChefOrderStatusUpdateSerializer, OrderSerializer, OrderCreateSerializer, OrderStatusCountSerializer, OrderStatusLogSerializer, OrderStatusUpdateSerializer, DjChefOrderDetailSerializer
from .permissions import IsOrderInEditableState, IsOrderOwnerOrChef
from django_filters.rest_framework import DjangoFilterBackend
from django.utils import timezone
from pytz import timezone as pytz_timezone
from .utils import get_wechat_config, send_provider_notification
from django.shortcuts import get_object_or_404
from .services.wechat_pay_service import WechatPayService
from django.http import HttpResponse

logger = logging.getLogger(__name__)
#getcontext().prec = 2
class OrderListView(generics.ListCreateAPIView):
    permission_classes = [permissions.IsAuthenticated]
    
    def get_serializer_class(self):
        return OrderCreateSerializer if self.request.method == 'POST' else OrderSerializer
    
    def get_queryset(self):
        user = self.request.user
        if user.user_type == 'chef':
            return Order.objects.filter(chef=user.chef_profile)
        return Order.objects.filter(customer=user)
    
    def get_serializer_context(self):
        context = super().get_serializer_context()
        context['request'] = self.request
        return context

class OrderDetailView(generics.RetrieveUpdateAPIView):
    serializer_class = OrderSerializer
    permission_classes = [IsAuthenticated, IsOrderOwnerOrChef]

    def get_queryset(self):
        """
        优化查询集：仅关联存在的字段，移除对'dish'的无效关联
        """
        return Order.objects.select_related(
            'customer',  # 关联顾客（存在的外键）
            'chef',       # 关联厨师（存在的外键）
            # 'address'  # 若Order模型没有address外键，需注释掉（避免新增错误）
        ).prefetch_related(
            # 修正：OrderItem无'dish'关联，直接查询items，不额外关联
            Prefetch('items', queryset=OrderItem.objects.all()),  
            'status_logs'  # 关联状态日志（正常保留）
        )

    def perform_update(self, serializer):
        instance = serializer.instance
        new_status = serializer.validated_data.get('status')
        
        if new_status and new_status != instance.status:
            changed_by_type = "chef" if hasattr(self.request.user, 'chef') else "customer"
            OrderStatusLog.objects.create(
                order=instance,
                from_status=instance.status,
                to_status=new_status,
                changed_by=self.request.user,
                note=f"状态变更: {instance.status} → {new_status}（操作人：{changed_by_type}）"
            )
        serializer.save()
    
    def get_serializer_context(self):
        context = super().get_serializer_context()
        order = self.get_object()
        
        # 控制厨师联系方式显示
        if order.status not in ['confirmed', 'preparing', 'cooking']:
            context['hide_chef_contact'] = True
        
        # 用户坐标（供厨师距离计算）
        context['user_longitude'] = self.request.query_params.get('longitude')
        context['user_latitude'] = self.request.query_params.get('latitude')
        
        # 图片审核开关
        context['check_image_approval'] = self.request.query_params.get('check_image_approval') == '1'
        
        return context

class OrderViewSet(viewsets.ModelViewSet):
    serializer_class = OrderSerializer
    filter_backends = [DjangoFilterBackend]
    filterset_fields = ['status', 'chef_id']
    ordering_fields = ['created_at', 'booked_time']
    throttle_scope = 'orders'

    def get_queryset(self):
        return Order.objects.filter(
            customer=self.request.user
        ).select_related('chef', 'address')

    @action(detail=True, methods=['post'])
    def cancel(self, request, pk=None):
        order = self.get_object()
        if order.status not in ['pending', 'paid']:
            return Response(
                {'error': '当前状态不可取消'}, 
                status=status.HTTP_400_BAD_REQUEST
            )
        
        order.status = 'cancelled'
        order.save()
        return Response({'status': 'cancelled'})

    @action(detail=True, methods=['post'])
    def pay(self, request, pk=None):
        # 对接支付网关的逻辑
        order = self.get_object()
        if order.status != 'pending':
            return Response({"error": f"订单状态为 {order.status}，无法进行支付"}, status=status.HTTP_400_BAD_REQUEST)
        
        payment_method = request.data.get('payment_method', 'wechat')
        if payment_method == 'wechat':
            return self._process_wechat_pay(order, request)
        elif payment_method == 'balance':
            return self._process_balance_pay(order, request)
        else:
            return Response({"error": "不支持的支付方式"}, status=status.HTTP_400_BAD_REQUEST)

    def _process_wechat_pay(self, order, request):
        is_consumer = order.is_consumer_mini_program
        app_type = 'consumer' if is_consumer else 'provider'
        wechat_config = get_wechat_config(app_type)
        pay_service = WechatPayService(wechat_config)
        try:
            # 仅生成支付参数，不提前修改订单状态（等待回调确认后再更新）
            wechat_pay_params = pay_service.unified_order(order)
            # 移除此处提前将状态改为'paid'的错误逻辑
            return Response({
                'payment_method': 'wechat',
                'wechat_pay_params': wechat_pay_params,
                'status': order.status,  # 保持当前状态（pending）
                'order': OrderSerializer(order, context={'request': request}).data
            }, status=status.HTTP_200_OK)
        except Exception as e:
            logger.error(f"微信支付参数生成失败: {str(e)}", exc_info=True)
            return Response({"error": "微信支付处理失败，请稍后重试"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    def _process_balance_pay(self, order, request):
        customer = request.user
        if customer.balance < order.total_amount:
            return Response(
                {"error": "账户余额不足"},
                status=status.HTTP_400_BAD_REQUEST
            )
        
        customer.balance -= order.total_amount
        customer.save()
        
        order.change_status(
            to_status='paid',
            changed_by=request.user,
            note=f"用户使用余额支付成功"
        )
        # 标记时间槽
        try:
            time_slot = TimeSlot.objects.get(id=order.time_slot_id, chef=order.chef)
            time_slot.status = 'booked'
            time_slot.save(update_fields=['status'])
            logger.info(f"订单[{order.id}]时间槽[{time_slot.id}]已标记为已预订")
        except TimeSlot.DoesNotExist:
            logger.error(f"订单[{order.id}]关联的时间槽不存在")

         # 补充通知触发日志
        logger.info(f"准备向厨师[{order.chef.id}]发送通知（余额支付订单[{order.id}]）")
        notify_result = send_provider_notification(order.chef, order)
        logger.info(f"余额支付通知发送结果：{'成功' if notify_result else '失败'}（订单[{order.id}]）")
        
        return Response({
            'payment_method': 'balance',
            'status': 'paid',
            'order': OrderSerializer(order, context={'request': request}).data
        }, status=status.HTTP_200_OK)

    def get_permissions(self):
        if self.action in ['update', 'partial_update']:
            return [IsOrderOwnerOrChef(), IsOrderInEditableState()]
        return [IsOrderOwnerOrChef()]

class OrderStatusLogView(generics.ListAPIView):
    """
    获取订单状态变更历史
    GET /api/orders/{order_id}/status-logs/
    """
    serializer_class = OrderStatusLogSerializer
    permission_classes = [permissions.IsAuthenticated, IsOrderOwnerOrChef]
    pagination_class = None  # 通常日志不需要分页

    def get_queryset(self):
        order_id = self.kwargs['order_id']
        return OrderStatusLog.objects.filter(
            order_id=order_id
        ).select_related(
            'changed_by'
        ).order_by('-created_at')

class OrderCreateView(generics.CreateAPIView):
    """
    创建新订单（集成微信支付V3接口）
    POST /api/orders/
    功能：验证业务合法性 → 创建订单及关联数据 → 调用微信支付接口生成参数 → 返回结果
    """
    queryset = Order.objects.all()
    serializer_class = OrderCreateSerializer
    permission_classes = [permissions.IsAuthenticated]

    # @transaction.atomic  # 确保所有数据库操作在同一事务中
    # def perform_create(self, serializer):
    #     start_time = timezone.now()
    #     user = self.request.user
    #     request_data = self.request.data
    #     logger.info(f"用户[{user.id}]开始创建订单，原始请求数据: {json.dumps(request_data, ensure_ascii=False)}")

    #     # --------------------------
    #     # 1. 验证核心业务资源
    #     # --------------------------
    #     # 1.1 验证厨师存在
    #     chef_id = request_data.get('chef')
    #     try:
    #         chef = DjChef.objects.get(id=chef_id)
    #     except DjChef.DoesNotExist:
    #         logger.warning(f"用户[{user.id}]创建订单失败：厨师ID[{chef_id}]不存在")
    #         raise ValueError(f"厨师不存在（ID: {chef_id}）")

    #     # 1.2 验证时间槽存在且未被占用
    #     time_slot_id = request_data.get('time_slot_id')
    #     try:
    #         # 加行锁防止并发抢占
    #         time_slot = TimeSlot.objects.select_for_update().get(id=time_slot_id, chef=chef)
    #     except TimeSlot.DoesNotExist:
    #         logger.warning(f"用户[{user.id}]创建订单失败：时间槽ID[{time_slot_id}]不存在或不属于厨师[{chef_id}]")
    #         raise ValueError(f"时间槽不存在或已被占用（ID: {time_slot_id}）")

    #     # 1.3 验证订单项合法性
    #     items = request_data.get('items', [])
    #     if not items:
    #         logger.warning(f"用户[{user.id}]创建订单失败：订单项为空")
    #         raise ValueError("订单项不能为空")

    #     # 1.4 验证每个菜品存在且计算实际金额
    #     calculated_subtotal = Decimal('0.00')  # 后端计算的商品总价
    #     valid_items = []
    #     for item in items:
    #         dish_id = item.get('dish_id')
    #         quantity = item.get('quantity', 0)
    #         # 关键修改：将前端价格直接转为 Decimal（避免 float 精度丢失）
    #         front_price_str = item.get('price', '0')
    #         try:
    #             front_price = Decimal(front_price_str)  # 直接从字符串转 Decimal
    #         except InvalidOperation:
    #             logger.warning(f"用户[{user.id}]创建订单失败：菜品[{dish_id}]价格格式错误（{front_price_str}）")
    #             raise ValueError(f"菜品价格格式错误（{front_price_str}）")

    #         # 验证菜品存在
    #         try:
    #             dish = DjDish.objects.get(id=dish_id, chef=chef)  # 确保菜品属于当前厨师
    #         except DjDish.DoesNotExist:
    #             logger.warning(f"用户[{user.id}]创建订单失败：菜品ID[{dish_id}]不存在或不属于厨师[{chef_id}]")
    #             raise ValueError(f"菜品不存在（ID: {dish_id}）")

    #         # 验证数量为正整数
    #         if not isinstance(quantity, int) or quantity <= 0:
    #             logger.warning(f"用户[{user.id}]创建订单失败：菜品[{dish_id}]数量无效（{quantity}）")
    #             raise ValueError(f"菜品[{dish.name}]数量必须为正整数")

    #         # 验证前端单价与实际一致（防止篡改）
    #         if not (abs(Decimal(str(front_price)) - dish.display_price) < Decimal('0.01')):
    #             logger.warning(
    #                 f"用户[{user.id}]创建订单失败：菜品[{dish_id}]单价不一致（前端: {front_price}, 实际: {dish.display_price}）"
    #             )
    #             raise ValueError(f"菜品[{dish.name}]价格异常，请刷新重试")

    #         # 累计计算总价
    #         item_total = dish.display_price * quantity
    #         calculated_subtotal += item_total
    #         valid_items.append({
    #             'dish': dish,
    #             'quantity': quantity,
    #             'price': dish.display_price,
    #             'item_total': item_total
    #         })

    #     # --------------------------
    #     # 2. 计算订单金额（后端主导）
    #     # --------------------------
    #     service_fee = calculated_subtotal * Decimal('0.1')  # 服务费为商品总价的10%
    #     total_amount = calculated_subtotal + service_fee  # 总金额=商品总价+服务费

    #     # --------------------------
    #     # 3. 保存订单（覆盖前端传递的金额）
    #     # --------------------------
    #     # 1. 定义时段到具体时间的映射关系
    #     period_time_map = {
    #         'lunch': '11:00',   # 午餐对应 11:00
    #         'dinner': '18:00'   # 晚餐对应 18:00
    #     }

    #     # 3. 从time_slot中获取日期和时段，组合成booked_time
    #     period = time_slot.period
    #     date = time_slot.date  # 假设date是date对象（如2023-10-01）
    #     time_str = period_time_map.get(period, '11:00')

    #     # 4. 组合为naive datetime（无时区）
    #     naive_booked_time = timezone.datetime.combine(
    #         date, 
    #         timezone.datetime.strptime(time_str, "%H:%M").time()
    #     )

    #     # 5. 明确指定为Asia/Shanghai时区（关键修复）
    #     shanghai_tz = pytz_timezone('Asia/Shanghai')
    #     booked_time = shanghai_tz.localize(naive_booked_time, is_dst=None)
    #     print(f"【响应时间】{booked_time}")

    #     order_data = {
    #         **serializer.validated_data,
    #         'subtotal': calculated_subtotal,
    #         'service_fee': service_fee,
    #         'total_amount': total_amount,
    #         'chef': chef,
    #         'status': 'pending',  # 强制初始状态为待支付
    #         'booked_time': booked_time
    #     }

    #     # 保存订单（关联用户）
    #     order = serializer.save(customer=user,** order_data)
    #     logger.info(f"订单[{order.order_number}]创建成功（ID: {order.id}），后端计算金额: 商品总价={calculated_subtotal}, 服务费={service_fee}, 总计={total_amount}")

    #     # --------------------------
    #     # 4. 创建订单项（关联订单）
    #     # --------------------------
    #     # order_items = [
    #     #     OrderItem(
    #     #         order=order,
    #     #         dish=item['dish'],
    #     #         quantity=item['quantity'],
    #     #         price=item['price']
    #     #     ) for item in valid_items
    #     # ]
    #     # OrderItem.objects.bulk_create(order_items)
    #     # logger.info(f"订单[{order.id}]已关联{len(order_items)}个订单项，菜品ID: {[item.dish.id for item in order_items]}")

    #     # --------------------------
    #     # 5. 创建初始状态日志
    #     # --------------------------
    #     OrderStatusLog.objects.create(
    #         order=order,
    #         from_status=None,
    #         to_status='pending',
    #         changed_by=user,
    #         note='订单创建，待支付',
    #         ip_address=self.request.META.get('REMOTE_ADDR', 'unknown')
    #     )
    #     logger.info(f"订单[{order.id}]状态日志创建完成，初始状态: pending")

    #     # --------------------------
    #     # 6. 生成微信支付参数（对接微信支付V3接口）
    #     # --------------------------
    #     try:
    #         pay_params = self.generate_wechat_pay_params(order)
    #         order.pay_params = json.dumps(pay_params)  # 保存支付参数到订单
    #         order.save(update_fields=['pay_params'])
    #         logger.info(f"订单[{order.id}]支付参数生成成功")
    #     except Exception as e:
    #         logger.error(f"订单[{order.id}]生成支付参数失败: {str(e)}", exc_info=True)
    #         raise ValueError("支付参数生成失败，请重试")

    #     # 记录耗时
    #     end_time = timezone.now()
    #     logger.info(
    #         f"用户[{user.id}]订单创建完成，耗时{(end_time - start_time).total_seconds():.2f}秒，"
    #         f"订单号: {order.order_number}"
    #     )
    @transaction.atomic  
    def perform_create(self, serializer):
        # --------------------------
        # 关键修改1：start_time 加8小时（用于后续耗时计算，确保与实际时间一致）
        # --------------------------
        start_time = timezone.now() + timedelta(hours=8)  # 临时+8小时
        user = self.request.user
        request_data = self.request.data
        logger.info(f"用户[{user.id}]开始创建订单，原始请求数据: {json.dumps(request_data, ensure_ascii=False)}")

        # 1. 验证核心业务资源（逻辑不变，省略...）
        # ...（厨师、时间槽、订单项验证逻辑保持不变）...
        chef_id = request_data.get('chef')
        try:
            chef = DjChef.objects.get(id=chef_id)
        except DjChef.DoesNotExist:
            logger.warning(f"用户[{user.id}]创建订单失败：厨师ID[{chef_id}]不存在")
            raise ValueError(f"厨师不存在（ID: {chef_id}）")

        # 1.2 验证时间槽存在且未被占用
        time_slot_id = request_data.get('time_slot_id')
        try:
            # 加行锁防止并发抢占
            time_slot = TimeSlot.objects.select_for_update().get(id=time_slot_id, chef=chef)
        except TimeSlot.DoesNotExist:
            logger.warning(f"用户[{user.id}]创建订单失败：时间槽ID[{time_slot_id}]不存在或不属于厨师[{chef_id}]")
            raise ValueError(f"时间槽不存在或已被占用（ID: {time_slot_id}）")

        # 1.3 验证订单项合法性
        items = request_data.get('items', [])
        if not items:
            logger.warning(f"用户[{user.id}]创建订单失败：订单项为空")
            raise ValueError("订单项不能为空")

        # 1.4 验证每个菜品存在且计算实际金额
        calculated_subtotal = Decimal('0.00')  # 后端计算的商品总价
        valid_items = []
        for item in items:
            dish_id = item.get('dish_id')
            quantity = item.get('quantity', 0)
            # 关键修改：将前端价格直接转为 Decimal（避免 float 精度丢失）
            front_price_str = item.get('price', '0')
            try:
                front_price = Decimal(front_price_str)  # 直接从字符串转 Decimal
            except InvalidOperation:
                logger.warning(f"用户[{user.id}]创建订单失败：菜品[{dish_id}]价格格式错误（{front_price_str}）")
                raise ValueError(f"菜品价格格式错误（{front_price_str}）")

            # 验证菜品存在
            try:
                dish = DjDish.objects.get(id=dish_id, chef=chef)  # 确保菜品属于当前厨师
            except DjDish.DoesNotExist:
                logger.warning(f"用户[{user.id}]创建订单失败：菜品ID[{dish_id}]不存在或不属于厨师[{chef_id}]")
                raise ValueError(f"菜品不存在（ID: {dish_id}）")

            # 验证数量为正整数
            if not isinstance(quantity, int) or quantity <= 0:
                logger.warning(f"用户[{user.id}]创建订单失败：菜品[{dish_id}]数量无效（{quantity}）")
                raise ValueError(f"菜品[{dish.name}]数量必须为正整数")

            # 验证前端单价与实际一致（防止篡改）
            if not (abs(Decimal(str(front_price)) - dish.display_price) < Decimal('0.01')):
                logger.warning(
                    f"用户[{user.id}]创建订单失败：菜品[{dish_id}]单价不一致（前端: {front_price}, 实际: {dish.display_price}）"
                )
                raise ValueError(f"菜品[{dish.name}]价格异常，请刷新重试")

            # 累计计算总价
            item_total = dish.display_price * quantity
            calculated_subtotal += item_total
            valid_items.append({
                'dish': dish,
                'quantity': quantity,
                'price': dish.display_price,
                'item_total': item_total
            })
        # --------------------------
        # 关键修改2：booked_time 加8小时（临时处理时区问题）
        # --------------------------
        service_fee = calculated_subtotal * Decimal('0.1')  # 服务费为商品总价的10%
        total_amount = calculated_subtotal + service_fee  # 总金额=商品总价+服务费
        period_time_map = {
            'lunch': '11:00',   
            'dinner': '18:00'   
        }
        period = time_slot.period
        date = time_slot.date  # 假设为date对象（如2023-10-01）
        time_str = period_time_map.get(period, '11:00')

        # 组合为naive datetime后，先加8小时，再附加上海时区
        naive_booked_time = timezone.datetime.combine(
            date, 
            timezone.datetime.strptime(time_str, "%H:%M").time()
        ) + timedelta(hours=8)  # 临时+8小时

        shanghai_tz = pytz_timezone('Asia/Shanghai')
        booked_time = shanghai_tz.localize(naive_booked_time, is_dst=None)
        logger.info(f"【临时处理】booked_time 加8小时后: {booked_time}")

        # --------------------------
        # 关键修改3：订单数据中，若有其他时间字段（如自定义create_at）需加8小时
        # --------------------------
        # 若Order模型的create_at是手动设置（非auto_now_add），需添加：
        # current_time = timezone.now() + timedelta(hours=8)
        # 并在order_data中加入 'create_at': current_time

        order_data = {
            **serializer.validated_data,
            'subtotal': calculated_subtotal,
            'service_fee': service_fee,
            'total_amount': total_amount,
            'chef': chef,
            'status': 'pending',
            'booked_time': booked_time  # 已加8小时的时间
        }

        # 保存订单（关联用户）
        order = serializer.save(customer=user,** order_data)
        logger.info(f"订单[{order.order_number}]创建成功（ID: {order.id}），后端计算金额: 商品总价={calculated_subtotal}, 服务费={service_fee}, 总计={total_amount}")

        # --------------------------
        # 关键修改4：状态日志的时间（若日志模型有time字段，需加8小时）
        # --------------------------
        OrderStatusLog.objects.create(
            order=order,
            from_status=None,
            to_status='pending',
            changed_by=user,
            note='订单创建，待支付',
            ip_address=self.request.META.get('REMOTE_ADDR', 'unknown'),
            # 若日志模型有time字段（如log_time），需添加：
            # log_time = timezone.now() + timedelta(hours=8)
        )
        logger.info(f"订单[{order.id}]状态日志创建完成，初始状态: pending")

        # --------------------------
        # 关键修改5：end_time 加8小时（确保耗时计算与实际时间一致）
        # --------------------------
        # --------------------------
        # 6. 生成微信支付参数（对接微信支付V3接口）
        # --------------------------
        try:
            pay_params = self.generate_wechat_pay_params(order)
            order.pay_params = json.dumps(pay_params)  # 保存支付参数到订单
            order.save(update_fields=['pay_params'])
            logger.info(f"订单[{order.id}]支付参数生成成功")
        except Exception as e:
            logger.error(f"订单[{order.id}]生成支付参数失败: {str(e)}", exc_info=True)
            raise ValueError("支付参数生成失败，请重试")

        # 记录耗时
        end_time = timezone.now()
        logger.info(
            f"用户[{user.id}]订单创建完成，耗时{(end_time - start_time).total_seconds():.2f}秒，"
            f"订单号: {order.order_number}"
        )

    def create(self, request, *args, **kwargs):
        try:
            required_fields = ['chef', 'time_slot_id', 'items']
            missing_fields = [f for f in required_fields if f not in request.data]
            if missing_fields:
                return Response(
                    {"detail": f"缺少必要参数：{', '.join(missing_fields)}"},
                    status=status.HTTP_400_BAD_REQUEST
                )

            # 1. 验证并创建订单
            serializer = self.get_serializer(data=request.data)
            serializer.is_valid(raise_exception=True)
            order = self.perform_create(serializer)

            # 2. 构造响应数据
            headers = self.get_success_headers(serializer.data)
            response_data = serializer.data
            if hasattr(order, 'pay_params'):
                response_data['pay_params'] = order.pay_params
                logger.info(f"订单[{order.id}]响应已附加支付参数")

            return Response(response_data, status=status.HTTP_201_CREATED, headers=headers)

        except ValueError as e:
            logger.error(f"用户[{request.user.id}]订单创建业务失败: {str(e)}")
            return Response(
                {"detail": str(e)},
                status=status.HTTP_400_BAD_REQUEST
            )
        except Exception as e:
            logger.error(f"用户[{request.user.id}]订单创建系统失败: {str(e)}", exc_info=True)
            return Response(
                {"detail": "订单创建失败，请稍后重试"},
                status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )

    def generate_wechat_pay_params(self, order):
        """
        生成微信支付参数（对接微信支付V3 JSAPI接口）
        文档参考：https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_1.shtml
        """
        # 1. 获取微信支付配置
        wechat_config = settings.WECHAT_CONFIG['consumer']
        required_configs = ['appid', 'mchid', 'private_key', 'notify_url']
        missing_configs = [key for key in required_configs if key not in wechat_config]
        if missing_configs:
            raise RuntimeError(f"微信支付配置不完整：缺少{', '.join(missing_configs)}")

        appid = wechat_config['appid']
        mchid = wechat_config['mchid']
        private_key = wechat_config['private_key']
        notify_url = wechat_config['notify_url']

        # 2. 准备基础参数
        total_fee = int(order.total_amount * 100)  # 转换为分
        if total_fee <= 0:
            raise ValueError("订单金额必须大于0")

        nonce_str = self._generate_nonce_str()
        timestamp = str(int(time.time()))  # 秒级时间戳
        out_trade_no = order.order_number  # 商户订单号

        # 3. 获取用户openid（需确保用户表有openid字段）
        try:
            openid = order.customer.openid  # 假设用户模型有openid字段
            if not openid:
                raise ValueError("用户未绑定微信openid")
        except Exception as e:
            raise RuntimeError(f"获取用户openid失败: {str(e)}")

        # 4. 构建统一下单请求体
        body = {
            "appid": appid,
            "mchid": mchid,
            "description": f"订单-{out_trade_no}",  # 订单描述
            "out_trade_no": out_trade_no,
            "notify_url": notify_url,
            "payer": {"openid": openid},
            "amount": {
                "total": total_fee  # 订单总金额（分）
            },
            "scene_info": {
                "payer_client_ip": self.request.META.get('REMOTE_ADDR', '127.0.0.1')  # 用户IP
            }
        }

        # 5. 调用微信统一下单接口
        prepay_id = self._call_wechat_unified_order(
            body=body,
            mchid=mchid,
            private_key=private_key,
            nonce_str=nonce_str,
            timestamp=timestamp
        )

        # 6. 生成前端支付签名
        pay_sign = self._generate_pay_sign(
            appid=appid,
            prepay_id=prepay_id,
            nonce_str=nonce_str,
            timestamp=timestamp,
            private_key=private_key
        )

        # 7. 返回完整支付参数
        return {
            "timeStamp": timestamp,
            "nonceStr": nonce_str,
            "package": f"prepay_id={prepay_id}",
            "signType": "RSA",
            "paySign": pay_sign,
            "total_fee": total_fee
        }

    def _generate_nonce_str(self, length=32):
        """生成随机字符串"""
        chars = string.ascii_letters + string.digits
        return ''.join(random.choice(chars) for _ in range(length))

    def _call_wechat_unified_order(self, body, mchid, private_key, nonce_str, timestamp):
        """调用微信支付统一下单接口（JSAPI）"""
        url = "https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi"
        url_path = "/v3/pay/transactions/jsapi"  # 接口路径（用于签名）
        method = "POST"

        CERT_SERIAL_NO = "277DD028194EF2E328383732B4E61C1B2F5883E4"
        # 生成请求体JSON字符串（去除空格）
        body_str = json.dumps(body, separators=(',', ':'), ensure_ascii=False)
        sign_str = f"{method}\n{url_path}\n{timestamp}\n{nonce_str}\n{body_str}\n"
        # 生成请求签名
        signature = self._generate_request_sign(
            method=method,
            url_path=url_path,
            timestamp=timestamp,
            nonce_str=nonce_str,
            body=body_str,
            private_key=private_key
        )

        # 构建Authorization头
        auth_header = (
            f'WECHATPAY2-SHA256-RSA2048 mchid="{mchid}",nonce_str="{nonce_str}",'
            f"serial_no=\"{CERT_SERIAL_NO}\","
            f'timestamp="{timestamp}",signature="{signature}"'
        )

        # 发送请求
        try:
            response = requests.post(
                url=url,
                headers={
                    "Content-Type": "application/json",
                    "Authorization": auth_header,
                    "Accept": "application/json"
                },
                data=body_str.encode('utf-8'),
                timeout=10  # 设置超时时间
            )

        except requests.exceptions.RequestException as e:
            raise RuntimeError(f"调用微信支付接口失败: {str(e)}")

        # 处理响应
        if response.status_code != 200:
            raise RuntimeError(
                f"微信支付接口返回错误（{response.status_code}）: {response.text}"
            )

        result = response.json()
        if "prepay_id" not in result:
            raise RuntimeError(f"微信返回数据缺少prepay_id: {json.dumps(result)}")

        return result["prepay_id"]

    def _generate_request_sign(self, method, url_path, timestamp, nonce_str, body, private_key):
        """生成微信支付接口请求签名（修复版）"""
        # 1. 构造签名串（确保格式完全正确）
        sign_str = f"{method}\n{url_path}\n{timestamp}\n{nonce_str}\n{body}\n"
        
        try:
            # 2. 加载私钥
            private_key_obj = load_pem_private_key(
                private_key.encode('utf-8'),
                password=None,
                backend=default_backend()
            )
            
            # 3. 生成签名（使用SHA256-RSA）
            signature = private_key_obj.sign(
                sign_str.encode("utf-8"),
                padding.PKCS1v15(),
                hashes.SHA256()
            )
            
            # 4. 关键修复：使用Base64编码而非十六进制
            return base64.b64encode(signature).decode('utf-8')
            
        except Exception as e:
            raise RuntimeError(f"生成请求签名失败: {str(e)}")

    def _generate_pay_sign(self, appid, prepay_id, nonce_str, timestamp, private_key):
        """生成前端支付签名paySign（修复版）"""
        # 1. 修正签名串格式（微信官方要求格式）
        sign_str = f"{appid}\n{timestamp}\n{nonce_str}\nprepay_id={prepay_id}\n"
        
        try:
            # 2. 加载私钥
            private_key_obj = load_pem_private_key(
                private_key.encode("utf-8"),
                password=None,
                backend=default_backend()
            )
            
            # 3. 生成签名（使用SHA256-RSA）
            signature = private_key_obj.sign(
                sign_str.encode("utf-8"),
                padding.PKCS1v15(),
                hashes.SHA256()
            )
            
            # 4. 关键修复：使用Base64编码
            return base64.b64encode(signature).decode('utf-8')
            
        except Exception as e:
            raise RuntimeError(f"生成支付签名失败: {str(e)}")

@csrf_exempt
def wechat_pay_notify(request):
    """
    微信支付V3回调处理接口
    文档参考：https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_5.shtml
    """
    if request.method != 'POST':
        return HttpResponse('Method Not Allowed', status=405)

    try:
        # 1. 读取回调数据
        body = request.body.decode('utf-8')
        logger.info(f"收到微信支付回调，原始数据: {body}")
        data = json.loads(body)
        out_trade_no = data.get('out_trade_no')  # 商户订单号
        trade_state = data.get('trade_state')

        # 2. 验证回调签名（关键：防止伪造请求）
        wechat_config = settings.WECHAT_CONFIG['consumer']
        api_v3_key = wechat_config.get('api_v3_key')  # 微信商户平台设置的API v3密钥
        wechat_cert_serial = wechat_config.get('wechat_cert_serial')  # 微信支付平台证书序列号
        
        # 获取回调头部信息
        signature = request.META.get('HTTP_WECHATPAY_SIGNATURE')
        timestamp = request.META.get('HTTP_WECHATPAY_TIMESTAMP')
        nonce = request.META.get('HTTP_WECHATPAY_NONCE')
        serial = request.META.get('HTTP_WECHATPAY_SERIAL')

        if not all([signature, timestamp, nonce, serial]):
            logger.error("微信回调缺少必要头部信息")
            return _wx_notify_response(False, "缺少签名信息")

        # 验证签名（需结合微信支付平台证书，此处简化逻辑，实际需实现完整验签）
        
        # 参考实现：https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay4_1.shtml
        if not verify_wechat_signature(
            body=body,
            signature=signature,
            timestamp=timestamp,
            nonce=nonce,
            serial=serial,
            wechat_cert_serial=wechat_cert_serial
        ):
            logger.error("微信回调签名验证失败")
            return _wx_notify_response(False, "签名验证失败")

        # 3. 解密回调资源（微信V3回调数据加密存储在resource中）
        resource = data.get('resource', {})
        ciphertext = resource.get('ciphertext')
        associated_data = resource.get('associated_data', '')
        nonce_str = resource.get('nonce')

        if not ciphertext:
            logger.error("微信回调缺少加密数据")
            return _wx_notify_response(False, "缺少支付数据")

        # 解密（使用API v3密钥）
        from Crypto.Cipher import AES
        import base64
        key = api_v3_key.encode('utf-8')
        nonce_bytes = nonce_str.encode('utf-8')
        associated_data_bytes = associated_data.encode('utf-8')
        ciphertext_bytes = base64.b64decode(ciphertext)

        # AES-GCM解密
        cipher = AES.new(key, AES.MODE_GCM, nonce=nonce_bytes)
        cipher.update(associated_data_bytes)
        decrypted = cipher.decrypt_and_verify(ciphertext_bytes[:-16], ciphertext_bytes[-16:])
        payment_info = json.loads(decrypted.decode('utf-8'))
        logger.info(f"解密后的支付信息: {payment_info}")

        # 4. 处理支付结果
        out_trade_no = payment_info.get('out_trade_no')  # 商户订单号
        trade_state = payment_info.get('trade_state')    # 支付状态（SUCCESS为成功）

        order = get_object_or_404(Order, order_number=out_trade_no)
        logger.info(f"回调处理订单：{order.id}（订单号：{out_trade_no}），支付状态：{trade_state}")
        
        if trade_state == 'SUCCESS':
            if order.status == 'paid':
                logger.info(f"订单[{order.id}]已处理过支付成功，跳过重复处理")
                return HttpResponse(json.dumps({"code": "SUCCESS", "message": "OK"}), content_type='application/json')

            # 更新订单状态
            order.change_status(
                to_status='paid',
                changed_by=None,
                note=f"微信支付成功，交易号: {data.get('transaction_id')}"
            )
            
            # 标记时间槽
            try:
                time_slot = TimeSlot.objects.get(id=order.time_slot_id, chef=order.chef)
                time_slot.status = 'booked'
                time_slot.save(update_fields=['status'])
                logger.info(f"订单[{order.id}]时间槽[{time_slot.id}]已标记为已预订")
            except TimeSlot.DoesNotExist:
                logger.error(f"订单[{order.id}]关联的时间槽不存在")
            
            # 关键：添加通知触发前日志
            logger.info(f"准备向厨师[{order.chef.id}]发送通知（订单[{order.id}]）")
            notify_result = send_provider_notification(order.chef, order)
            logger.info(f"通知发送结果：{'成功' if notify_result else '失败'}（订单[{order.id}]）")
            
            logger.info(f"订单[{order.id}]微信支付成功处理完成")

        return HttpResponse(json.dumps({"code": "SUCCESS", "message": "OK"}), content_type='application/json')

    except Exception as e:
        logger.error(f"微信支付回调处理失败: {str(e)}", exc_info=True)
        return HttpResponse(json.dumps({"code": "SUCCESS", "message": "OK"}), content_type='application/json')
        # if not out_trade_no:
        #     logger.error("支付信息缺少商户订单号")
        #     return _wx_notify_response(False, "缺少订单号")

        # # 5. 更新订单状态
        # if trade_state == 'SUCCESS':
        #     with transaction.atomic():
        #         try:
        #             order = Order.objects.select_for_update().get(order_number=out_trade_no)
        #             if order.status != 'pending':
        #                 logger.warning(f"订单[{out_trade_no}]已处理，当前状态: {order.status}")
        #                 return _wx_notify_response(True)

        #             # 更新订单状态为已支付
        #             order.change_status(
        #                 to_status='paid',
        #                 changed_by=None,  # 系统自动更新
        #                 note=f"微信支付成功，微信交易号: {payment_info.get('transaction_id')}"
        #             )
        #             logger.info(f"订单[{out_trade_no}]支付成功，状态已更新为'paid'")

        #             # 标记时间槽为已预订（假设TimeSlot有booked字段）
        #             time_slot = TimeSlot.objects.get(id=order.time_slot_id)
        #             time_slot.booked = True
        #             time_slot.save()

        #             # 发送通知给厨师
        #             send_provider_notification(order.chef, order)
        #         except Order.DoesNotExist:
        #             logger.error(f"订单[{out_trade_no}]不存在")
        #             return _wx_notify_response(False, "订单不存在")
        #         except Exception as e:
        #             logger.error(f"更新订单[{out_trade_no}]状态失败: {str(e)}", exc_info=True)
        #             return _wx_notify_response(False, "处理订单失败")

        # # 6. 响应微信（必须返回SUCCESS，否则会重复回调）
        # return _wx_notify_response(True)

    except Exception as e:
        logger.error(f"微信回调处理异常: {str(e)}", exc_info=True)
        return _wx_notify_response(False, "服务器处理错误")


def _wx_notify_response(success, message=""):
    """生成微信回调要求的响应格式"""
    return_code = "SUCCESS" if success else "FAIL"
    return_msg = message if message else ("OK" if success else "处理失败")
    response = {
        "code": return_code,
        "message": return_msg
    }
    return HttpResponse(
        json.dumps(response, ensure_ascii=False),
        content_type="application/json",
        status=200
    )


def verify_wechat_signature(body, signature, timestamp, nonce, serial, wechat_cert_serial):
    """
    验证微信支付回调签名（简化实现）
    实际需使用微信支付平台证书验证签名，参考官方文档
    """
    # 1. 拼接签名串
    sign_str = f"{timestamp}\n{nonce}\n{body}\n"
    # 2. 获取微信支付平台证书（需提前下载并缓存）
    # 3. 使用证书公钥验证签名（以下为伪代码）
    # from cryptography.hazmat.primitives import hashes
    # from cryptography.hazmat.primitives.asymmetric import padding
    # public_key = ...  # 从微信证书中获取的公钥
    # try:
    #     public_key.verify(
    #         base64.b64decode(signature),
    #         sign_str.encode('utf-8'),
    #         padding.PSS(
    #             mgf=padding.MGF1(hashes.SHA256()),
    #             salt_length=padding.PSS.MAX_LENGTH
    #         ),
    #         hashes.SHA256()
    #     )
    #     return True
    # except:
    #     return False
    # 开发阶段可先返回True，生产环境必须实现完整验证
    return True  # 注意：生产环境需替换为真实验签逻辑


class UserOrderListView(generics.ListAPIView):
    """
    获取当前用户的所有订单列表
    GET /api/user/orders/
    """
    serializer_class = OrderSerializer
    permission_classes = [permissions.IsAuthenticated]
    filter_backends = [DjangoFilterBackend]
    filterset_fields = ['status', 'created_at']

    def get_queryset(self):
        return Order.objects.filter(
            customer=self.request.user
        ).select_related(
            'chef', 'chef__user'
        ).prefetch_related(
            'items'
        ).order_by('-created_at')

class RefundMixin:
    """退款逻辑通用Mixin"""
    
    def _process_refund(self, order, request, reason):
        """
        处理订单退款
        :param order: 主订单实例（Order）
        :param request: 请求对象
        :param reason: 退款原因
        :return: 退款结果字典
        """
        if order.status not in ['paid', 'booked']:
            logger.warning(f"订单[{order.id}]无需退款，当前状态: {order.status}")
            return {"status": "SKIPPED", "reason": "订单未支付或无需退款"}

        # 微信支付退款
        if order.payment_method == 'wechat':
            return self._wechat_refund(order, request, reason)
        
        # 余额支付退款
        elif order.payment_method == 'balance':
            return self._balance_refund(order, request, reason)
        
        # 其他支付方式（需手动退款）
        else:
            return self._manual_refund(order, request, reason)
    
    def _wechat_refund(self, order, request, reason):
        """微信支付退款处理"""
        from .services import WechatRefundService
        from .utils import get_wechat_config
        
        is_consumer = order.is_consumer_mini_program
        app_type = 'consumer' if is_consumer else 'provider'
        wechat_config = get_wechat_config(app_type)
        refund_service = WechatRefundService(wechat_config)
        
        try:
            # 调用微信退款接口
            refund_result = refund_service.create_refund(
                order,
                reason=reason
            )
            
            # 更新订单退款状态
            order.refund_status = 'PROCESSING'
            order.out_refund_no = refund_result.get('out_refund_no')
            order.refund_amount = order.total_amount
            order.refund_reason = reason
            order.save(update_fields=['refund_status', 'out_refund_no', 'refund_amount', 'refund_reason'])
            
            # 记录退款日志
            OrderStatusLog.objects.create(
                order=order,
                from_status=order.status,
                to_status=order.status,  # 状态不变，仅记录退款
                changed_by=request.user,
                note=f"发起微信自动退款: {order.refund_amount}元，退款单号: {order.out_refund_no}"
            )
            
            logger.info(f"订单[{order.id}]微信退款发起成功，退款单号: {order.out_refund_no}")
            return {"status": "PROCESSING", "refund_no": order.out_refund_no}
            
        except Exception as e:
            logger.error(f"订单[{order.id}]微信退款失败: {str(e)}", exc_info=True)
            raise  # 抛出异常，触发事务回滚
    
    def _balance_refund(self, order, request, reason):
        """余额支付退款（直接退回用户余额）"""
        with transaction.atomic():
            # 恢复用户余额
            customer = order.customer
            customer.balance += order.total_amount
            customer.save(update_fields=['balance'])
            
            # 更新订单退款状态
            order.refund_status = 'SUCCESS'
            order.refund_amount = order.total_amount
            order.refund_time = timezone.now()
            order.refund_reason = reason
            order.save(update_fields=['refund_status', 'refund_amount', 'refund_time', 'refund_reason'])
            
            # 记录日志
            OrderStatusLog.objects.create(
                order=order,
                from_status=order.status,
                to_status=order.status,
                changed_by=request.user,
                note=f"余额自动退款: {order.refund_amount}元，已退回用户余额"
            )
            
            logger.info(f"订单[{order.id}]余额退款成功，用户[{customer.id}]余额已恢复")
            return {"status": "SUCCESS", "refund_amount": float(order.refund_amount)}
    
    def _manual_refund(self, order, request, reason):
        """其他支付方式（需手动退款）"""
        order.refund_status = 'PENDING'
        order.refund_reason = reason
        order.save(update_fields=['refund_status', 'refund_reason'])
        
        OrderStatusLog.objects.create(
            order=order,
            from_status=order.status,
            to_status=order.status,
            changed_by=request.user,
            note=f"订单已取消，支付方式为{order.payment_method}，需手动处理退款: {reason}"
        )
        
        logger.warning(f"订单[{order.id}]需手动退款，支付方式: {order.payment_method}")
        return {"status": "PENDING", "method": order.payment_method, "reason": "需手动退款"}
    
class OrderCancelView(generics.UpdateAPIView, RefundMixin):
    """消费者取消订单视图（支持自动退款）"""
    queryset = Order.objects.all()
    serializer_class = OrderStatusUpdateSerializer
    permission_classes = [IsOrderOwnerOrChef]

    @transaction.atomic  # 保证状态变更与退款的原子性
    def perform_update(self, serializer):
        order = self.get_object()
        new_status = 'cancelled'
        user = self.request.user
        
        # 1. 验证订单状态是否允许取消
        allowed_statuses = ['pending', 'paid', 'booked']  # 包含booked状态
        if order.status not in allowed_statuses:
            logger.warning(
                f"用户[{user.id}]尝试取消不允许取消的订单，"
                f"订单号: {order.order_number}, 当前状态: {order.status}"
            )
            raise serializers.ValidationError(
                f'当前订单状态为 {order.get_status_display()}，不允许取消。'
            )

        # 2. 处理退款（仅paid/booked状态需要）
        refund_result = None
        if order.status in ['paid', 'booked']:
            try:
                refund_result = self._process_refund(
                    order=order,
                    request=self.request,
                    reason=f"用户[{user.id}]主动取消订单"
                )
            except Exception as e:
                # 退款失败时回滚订单状态变更
                logger.error(f"订单[{order.id}]取消失败（退款异常）: {str(e)}", exc_info=True)
                raise  # 触发事务回滚

        # 3. 更新订单状态为取消
        order.change_status(
            to_status=new_status,
            changed_by=user,
            note=f"用户[{user.id}]取消订单，退款状态: {refund_result.get('status') if refund_result else '无需退款'}",
            request=self.request
        )

        logger.info(
            f"订单取消成功，订单号: {order.order_number}, "
            f"用户: {user.id}, 原状态: {order.status}, 退款状态: {refund_result.get('status') if refund_result else '无需退款'}"
        )

class OrderPayView(APIView):
    """处理订单支付的视图"""
    permission_classes = [permissions.IsAuthenticated]
    
    def post(self, request, pk):
        try:
            order = Order.objects.get(pk=pk, customer=request.user)
        except Order.DoesNotExist:
            return Response({"error": "订单不存在或您无权访问"}, status=status.HTTP_404_NOT_FOUND)
        
        # 验证订单状态是否可以支付
        if order.status != 'pending':
            return Response({"error": f"订单状态为 {order.status}，无法进行支付"}, status=status.HTTP_400_BAD_REQUEST)
        
        # 获取支付方式
        payment_method = request.data.get('payment_method', 'wechat')
        
        if payment_method == 'wechat':
            # 微信支付逻辑
            return self._process_wechat_pay(order, request)
        elif payment_method == 'balance':
            # 余额支付逻辑
            return self._process_balance_pay(order, request)
        else:
            return Response({"error": "不支持的支付方式"}, status=status.HTTP_400_BAD_REQUEST)
    
    def _process_wechat_pay(self, order, request):
        """处理微信支付"""
        is_consumer = order.is_consumer_mini_program
        app_type = 'consumer' if is_consumer else 'provider'
        wechat_config = get_wechat_config(app_type)
        pay_service = WechatPayService(wechat_config)
        try:
            wechat_pay_params = pay_service.unified_order(order)
            order.change_status(
                to_status='paid',
                changed_by=request.user,
                note=f"用户使用微信支付成功"
            )
            return Response({
                'payment_method': 'wechat',
                'wechat_pay_params': wechat_pay_params,
                'status': 'paid',
                'order': OrderSerializer(order, context={'request': request}).data
            }, status=status.HTTP_200_OK)
        except Exception as e:
            return Response({"error": "微信支付处理失败，请稍后重试"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    
    def _process_balance_pay(self, order, request):
        customer = request.user
        if customer.balance < order.total_amount:
            return Response(
                {"error": "账户余额不足"},
                status=status.HTTP_400_BAD_REQUEST
            )
        
        # 扣减余额
        customer.balance -= order.total_amount
        customer.save()
        
        # 更新订单状态为已支付
        order.change_status(
            to_status='paid',
            changed_by=request.user,
            note=f"用户使用余额支付成功"
        )
        
        # 标记时间槽为已预订
        try:
            time_slot = TimeSlot.objects.get(id=order.time_slot_id, chef=order.chef)
            time_slot.status = 'booked'
            time_slot.save(update_fields=['status'])
            logger.info(f"订单[{order.id}]时间槽[{time_slot.id}]已标记为已预订")
        except TimeSlot.DoesNotExist:
            logger.error(f"订单[{order.id}]关联的时间槽不存在")
        
        # 发送通知给厨师
        send_provider_notification(order.chef, order)
        
        return Response({
            'payment_method': 'balance',
            'status': 'paid',
            'order': OrderSerializer(order, context={'request': request}).data
        }, status=status.HTTP_200_OK)


    
# 厨师端
class ChefOrderListView(generics.ListAPIView):
    """
    获取当前厨师的所有订单列表（基于 DjChefOrder 模型）
    GET /api/chef/orders/
    """
    serializer_class = DjChefOrderSerializer
    permission_classes = [permissions.IsAuthenticated]
    filter_backends = [DjangoFilterBackend, filters.OrderingFilter]
    filterset_fields = ['status', 'service_date']  # 支持按状态和服务日期筛选
    ordering_fields = ['service_date', 'created_at', 'status']
    ordering = ['-service_date', '-service_time']  # 默认按服务日期倒序
    def dispatch(self, request, *args, **kwargs):
        """处理 OPTIONS 预检请求"""
        if request.method == 'OPTIONS':
            return HttpResponse(status=200)
        return super().dispatch(request, *args, **kwargs)

    def get_queryset(self):
        query_param_user_id = self.request.query_params.get('user_id')
        chef_id = query_param_user_id

        # 2. 验证chef_id有效性
        if not chef_id or not chef_id.isdigit():
            return DjChefOrder.objects.none()

        # 3. 检查DjChef表中是否存在id=45的记录
        try:
            chef = DjChef.objects.get(id=int(chef_id))
        except DjChef.DoesNotExist:
            return DjChefOrder.objects.none()

        # 4. 查询该厨师的订单
        orders = DjChefOrder.objects.filter(chef_id=chef.id)

        # # 5. 打印该厨师的所有订单ID（方便验证）
        # order_ids = [str(o.id) for o in orders]
        # print(f"订单ID列表：{','.join(order_ids) if order_ids else '无订单'}")

        return orders

    def list(self, request, *args, **kwargs):
        # 重写list方法，添加自定义响应头，方便前端验证
        queryset = self.get_queryset()
        serializer = self.get_serializer(queryset, many=True)
        response = Response(serializer.data)
        
        # 添加响应头：返回后端实际收到的X-User-Id
        response['X-Received-User-Id'] = self.request.META.get('HTTP_USER_ID', '未收到')
        return response

class ChefOrderDetailView(generics.RetrieveAPIView):
    """
    厨师端查看订单详情（基于 DjChefOrder 模型）
    GET /api/orders/chef/orders/<int:pk>/
    """
    queryset = DjChefOrder.objects.all().select_related(
        'chef', 'customer', 'original_order'  # 修正：关联original_order而非time_slot
    ).prefetch_related('status_logs', 'original_order__items')  # 预加载订单项
    serializer_class = DjChefOrderDetailSerializer
    permission_classes = [permissions.IsAuthenticated, IsChefOwner]

    def get_object(self):
        time_slot_id = self.kwargs.get('pk')
        logger.info(f"获取厨师订单详情 - 前端传递的time_slot_id: {time_slot_id}")
        try:
            # 联合查询并打印SQL（调试用）
            queryset = self.get_queryset()
            logger.debug(f"查询语句: {str(queryset.filter(original_order__time_slot_id=time_slot_id).query)}")
            
            obj = get_object_or_404(
                queryset,
                original_order__time_slot_id=time_slot_id
            )
            self.check_object_permissions(self.request, obj)
            logger.info(f"成功查询到厨师订单: ID={obj.id}, 订单号={obj.order_number}")
            return obj
        except Exception as e:
            logger.error(f"查询厨师订单失败: {str(e)}, time_slot_id={time_slot_id}", exc_info=True)
            raise  # 继续抛出异常让DRF处理

    def get_serializer_context(self):
        context = super().get_serializer_context()
        try:
            order = self.get_object()
            context['hide_contact'] = order.status not in ['confirmed', 'serving', 'completed']
            logger.debug(f"序列化器上下文: {context}, 订单状态={order.status}")
        except Exception as e:
            logger.error(f"获取序列化器上下文失败: {str(e)}", exc_info=True)
        return context

    def retrieve(self, request, *args, **kwargs):
        try:
            instance = self.get_object()
            serializer = self.get_serializer(instance)
            response_data = serializer.data
            
            # 记录返回的关键数据（避免日志过大）
            print(f"【响应数据】{response_data}")
            logger.info(
                f"返回厨师订单详情 - ID={instance.id}, "
                f"状态={instance.status}, "
                f"响应字段数={len(response_data.keys())}"
            )
            logger.debug(f"完整响应数据: {response_data}")  # 生产环境可注释
            
            return Response(response_data)
        except Exception as e:
            logger.error(f"返回订单详情失败: {str(e)}", exc_info=True)
            return Response(
                {"error": "获取订单详情失败"},
                status=500
            )
class ChefOrderBaseView(generics.UpdateAPIView):
    """订单操作基础类，复用权限和序列化器"""
    queryset = DjChefOrder.objects.all()
    serializer_class = DjChefOrderStatusUpdateSerializer
    permission_classes = [IsChefOwner]  # 补充IsAuthenticated确保登录

    def get_object(self):
        """通过URL中的orderid查询订单"""     
        # 获取订单ID
        order_id = self.kwargs.get('pk')    
        # 执行查询
        try:
            obj = get_object_or_404(DjChefOrder, id=order_id)
            return obj
        except Exception as e:

            raise  

    def get_chef(self, request):
        """获取当前登录用户关联的DjChef"""
        try:
            return DjChef.objects.get(user=request.user)
        except DjChef.DoesNotExist:
            raise serializers.ValidationError("当前用户不是厨师")
        
class ChefOrderRejectView(ChefOrderBaseView, RefundMixin):
    """厨师拒单视图（同步状态+自动退款）"""
    
    @transaction.atomic
    def update(self, request, *args, **kwargs):
        order = self.get_object()  # DjChefOrder实例
        current_chef = self.get_chef(request)
        original_order = order.original_order  # 主订单（Order）
        note = request.data.get('note', "厨师取消订单")

        # 1. 状态验证（子订单和主订单的允许状态分开定义）
        # 子订单允许状态：pending/confirmed/booked（厨师可操作的状态）
        allowed_chef_order_statuses = ['pending', 'confirmed', 'booked']
        # 主订单允许状态：除了子订单的状态，额外包含paid（已支付但未完成的状态）
        allowed_main_order_statuses = ['pending', 'confirmed', 'booked', 'paid']
        
        if (order.status not in allowed_chef_order_statuses 
            or original_order.status not in allowed_main_order_statuses):
            logger.warning(
                f"厨师[{current_chef.id}]尝试拒单不允许的订单，"
                f"订单号: {original_order.order_number}, "
                f"DjChefOrder状态: {order.status}, 主订单状态: {original_order.status}"
            )
            return Response(
                {"detail": "只有待确认、已确认、已预订或已支付的订单可以拒绝"},
                status=status.HTTP_400_BAD_REQUEST
            )

        # 2. 处理退款（仅paid/booked状态需要）
        refund_result = None
        if original_order.status in ['paid', 'booked']:
            try:
                refund_result = self._process_refund(
                    order=original_order,
                    request=request,
                    reason=f"厨师[{current_chef.id}]拒绝接单: {note}"
                )
            except Exception as e:
                logger.error(f"订单[{original_order.id}]拒单失败（退款异常）: {str(e)}", exc_info=True)
                return Response(
                    {"detail": "订单拒绝失败，退款处理异常，请联系客服"},
                    status=status.HTTP_500_INTERNAL_SERVER_ERROR
                )

        # 3. 同步更新两个模型的状态为已取消
        # 更新DjChefOrder
        order.change_status(
            to_status='cancelled',
            changed_by=current_chef,
            note=f"{note}，退款状态: {refund_result.get('status') if refund_result else '无需退款'}"
        )
        order.save()

        # 同步更新主订单（Order）
        original_order.change_status(
            to_status='cancelled',
            changed_by=request.user,
            note=f"厨师[{current_chef.id}]拒绝接单，同步取消主订单，退款状态: {refund_result.get('status') if refund_result else '无需退款'}"
        )

        # 4. 释放关联的档期
        self._release_time_slot(order)

        logger.info(
            f"厨师拒单成功，订单号: {original_order.order_number}, "
            f"厨师: {current_chef.id}, 退款状态: {refund_result.get('status') if refund_result else '无需退款'}"
        )

        # 5. 返回更新后的订单
        serializer = self.get_serializer(order)
        return Response(serializer.data)
    
    def _release_time_slot(self, chef_order):
        """
        释放订单关联的时间槽：将状态从'booked'改为'available'
        处理逻辑：
        1. 验证订单与时间槽的关联关系（通过original_order间接关联）
        2. 仅当时间槽当前为'booked'状态时才更新（避免重复操作）
        3. 完善日志和异常处理
        """
        try:
            # 1. 通过original_order获取原订单，再关联时间槽
            original_order = chef_order.original_order
            if not original_order:
                logger.warning(f"订单[{chef_order.id}]未关联原订单(original_order)，无法释放时间槽")
                return

            # 从原订单获取时间槽
            time_slot = original_order.time_slot
            if not time_slot:
                logger.warning(f"原订单[{original_order.id}]未关联时间槽，订单[{chef_order.id}]无需释放时间槽")
                return

            # 2. 仅当时间槽处于'booked'状态时才释放（避免无效操作）
            if time_slot.status != 'booked':
                logger.info(
                    f"时间槽[{time_slot.id}]当前状态为'{time_slot.status}'，无需释放（仅'booked'状态需要释放）"
                )
                return

            # 3. 更新时间槽状态为'available'
            time_slot.status = 'available'
            time_slot.save(update_fields=['status'])  # 仅更新status字段，优化性能

            logger.info(
                f"时间槽[{time_slot.id}]释放成功，订单号: {original_order.order_number}，"
                f"状态从'booked'更新为'available'"
            )

        except AttributeError as e:
            # 处理属性不存在的情况（如模型关联字段名错误）
            logger.error(
                f"释放时间槽失败：模型属性错误（可能是original_order或time_slot字段名不正确），错误信息: {str(e)}",
                exc_info=True
            )
        except Exception as e:
            # 捕获其他异常（如数据库错误），不阻断主流程
            logger.error(
                f"释放时间槽时发生未知错误，订单ID: {chef_order.id}，错误信息: {str(e)}",
                exc_info=True
            )

class ChefOrderStartView(ChefOrderBaseView):
    """厨师开始处理订单 - 同步更新两个模型状态"""
    
    @transaction.atomic
    def perform_update(self, serializer):
        order = self.get_object()  # DjChefOrder实例
        current_chef = self.get_chef(self.request)
        original_order = order.original_order  # 获取关联的Order实例

        # 1. 状态验证
        if order.status != 'confirmed' or original_order.status != 'confirmed':
            raise serializers.ValidationError("只有已确认的订单可以开始处理")

        # 2. 同步更新两个模型的状态为服务中
        # 更新DjChefOrder
        order.change_status(
            to_status='serving',
            changed_by=current_chef,
            note="厨师开始提供服务"
        )
        serializer.save(status='serving')

        # 同步更新Order
        original_order.change_status(
            to_status='serving',
            changed_by=self.request.user,
            note="厨师开始服务，同步更新主订单状态"
        )

class ChefOrderCompleteView(ChefOrderBaseView):
    """厨师标记订单完成 - 同步更新状态并累加钱包金额及交易流水"""
    
    def perform_update(self, serializer):
        order = self.get_object()  # DjChefOrder实例
        current_chef = self.get_chef(self.request)
        original_order = order.original_order  # 获取关联的Order实例

        # 1. 状态验证
        if order.status != 'serving' or original_order.status != 'serving':
            raise serializers.ValidationError("只有服务中的订单可以标记为完成")

        # 2. 获取订单收入金额（假设DjChefOrder中有chef_fee字段记录厨师收入）
        # 请根据实际字段名调整，例如order.income、order.chef_income等
        order_income = order.chef_income
        if order_income <= 0:
            raise serializers.ValidationError("订单收入金额异常，无法完成")

        # 3. 同步更新两个模型的状态为已完成
        # 更新DjChefOrder
        order.change_status(
            to_status='completed',
            changed_by=current_chef,
            note="厨师完成服务"
        )
        order.completed_at = timezone.now()
        serializer.save(status='completed', completed_at=order.completed_at)

        # 同步更新Order
        original_order.change_status(
            to_status='completed',
            changed_by=self.request.user,
            note="厨师完成服务，同步更新主订单状态"
        )
        original_order.completed_at = timezone.now()
        original_order.save()

        # 4. 处理金额变动及交易流水记录
        try:
            # 获取当前厨师ID
            chef_id = current_chef.id
            
            # 获取钱包实例（确保存在）
            wallet, created = DjChefWallet.objects.get_or_create(
                chef_id=chef_id,
                defaults={'balance': 0.00}
            )

            # 使用F()表达式原子更新，防止并发问题
            # 1. 更新钱包余额
            DjChefWallet.objects.filter(chef_id=chef_id).update(
                balance=F('balance') + order_income
            )
            
            # 2. 同时更新用户模型(DjChef)的balance字段
            DjChef.objects.filter(id=chef_id).update(
                balance=F('balance') + order_income
            )

            # 刷新实例获取最新数据
            wallet.refresh_from_db()
            current_chef.refresh_from_db()

            # 5. 创建交易流水记录
            # 生成唯一交易流水号（可根据实际需求调整格式）
            transaction_id = f"ORD-{original_order.order_number}-{timezone.now().strftime('%Y%m%d%H%M%S')}"
            
            DjWalletTransaction.objects.create(
                chef_id=chef_id,
                wallet=wallet,
                transaction_type='order_income',  # 订单收入类型
                amount=order_income,
                transaction_id=transaction_id,
                related_order=original_order,  # 关联主订单
                note=f"订单[{original_order.order_number}]完成收入",
                admin_note=f"厨师[{chef_id}]完成订单收入"
            )

            logger.info(
                f"订单[{original_order.order_number}]完成，"
                f"厨师[{chef_id}]收入¥{order_income}，"
                f"交易流水号: {transaction_id}"
            )

        except Exception as e:
            # 处理异常
            logger.error(
                f"订单[{original_order.order_number if original_order else '未知'}]完成后更新失败: {str(e)}",
                exc_info=True
            )
            raise  # 抛出异常让上层处理（触发事务回滚）
            

class ChefOrderAcceptView(ChefOrderBaseView):
    """厨师接单视图 - 同步更新两个模型状态"""
    
    @transaction.atomic
    def update(self, request, *args, **kwargs):
        print("\n===== ChefOrderAcceptView.update 开始 =====")
        logger.info(f"厨师接单请求：订单ID={kwargs.get('pk')}，用户={request.user.id}")
        # 1. 获取订单和厨师
        try:
            order = self.get_object()  # 调用父类的get_object
            logger.info(f"获取到DjChefOrder：ID={order.id}，status={order.status}")
        except Exception as e:
            return Response(
                {"detail": f"获取订单失败: {str(e)}"},
                status=status.HTTP_404_NOT_FOUND
            )
        if not hasattr(order, 'original_order') or order.original_order is None:
            logger.error(f"DjChefOrder[{order.id}]未关联主订单（original_order为None）")
            return Response(
                {"detail": "订单关联信息异常"},
                status=status.HTTP_400_BAD_REQUEST
            )
        
        current_chef = self.get_chef(request)
        original_order = order.original_order  # 获取关联的Order实例
        logger.info(f"关联的主订单Order：ID={original_order.id}，status={original_order.status}")

        # 1. 状态验证（修改为：允许pending或paid状态的订单被接受）
        valid_statuses = ['pending', 'paid']
        if order.status not in valid_statuses or original_order.status not in valid_statuses:
            logger.warning(f"DjChefOrder[{order.id}]状态无效：当前={order.status}，允许={valid_statuses}")
            return Response(
                {"detail": f"只有{valid_statuses}状态的订单可以接受"},
                status=status.HTTP_400_BAD_REQUEST
            )

        # 2. 生成虚拟号码（关联厨师和顾客）
        virtual_number = self._generate_virtual_number(order, current_chef)

        # 3. 关联或创建档期（标记为已预订）

        # 4. 同步更新两个模型的状态为已确认
        # 更新DjChefOrder
        order.change_status(
            to_status='confirmed',
            changed_by=current_chef,
            note="厨师接受订单"
        )
        order.customer_contact_number = virtual_number
        #order.time_slot = time_slot
        order.confirmed_at = timezone.now()
        order.save()

        # 同步更新Order
        original_order.change_status(
            to_status='confirmed',
            changed_by=request.user,
            note="厨师接受订单，同步更新主订单状态"
        )

        # 5. 返回更新后的订单
        serializer = self.get_serializer(order)
        return Response(serializer.data)

    # 确保实现以下辅助方法（如果之前未实现）
    def _generate_virtual_number(self, order, chef):
        """生成虚拟号码的逻辑（示例）"""
        # 实际项目中需替换为真实逻辑
        return f"138{order.id % 10000:04d}"


# 后台订单管理系统
class AdminOrderListView(generics.ListAPIView):
    """后台管理系统订单列表"""
    queryset = Order.objects.all().select_related('customer', 'chef', 'address')
    serializer_class = OrderSerializer
    permission_classes = [IsAdminUser]
    filter_backends = [DjangoFilterBackend]
    filterset_fields = ['status', 'payment_method', 'chef_id']
    ordering_fields = ['created_at', 'booked_time', 'total_amount']
    pagination_class = PageNumberPagination

class AdminOrderDetailView(generics.RetrieveUpdateDestroyAPIView):
    """后台管理系统订单详情"""
    queryset = Order.objects.all()
    serializer_class = OrderSerializer
    permission_classes = [IsAdminUser]
    
    def perform_destroy(self, instance):
        # 软删除逻辑
        instance.status = 'cancelled'
        instance.save()
        
        OrderStatusLog.objects.create(
            order=instance,
            from_status=instance.status,
            to_status='cancelled',
            changed_by=self.request.user,
            note='管理员删除订单'
        )

class OrderStatusUpdateView(generics.UpdateAPIView):
    """通用订单状态变更API"""
    queryset = Order.objects.all()
    serializer_class = OrderStatusUpdateSerializer
    
    def get_permission_classes(self):
        # 根据用户类型动态设置权限
        if self.request.user.user_type == 'chef':
            return [permissions.IsAuthenticated, IsChefOwner]
        return [permissions.IsAuthenticated, IsOrderOwnerOrChef]
    
    def perform_update(self, serializer):
        order = self.get_object()
        new_status = serializer.validated_data['status']
        
        # 状态转换规则
        status_rules = {
            # 消费端状态转换
            'customer': {
                'pending': ['cancelled'],
                'paid': ['cancelled'],
                'completed': ['refunded']
            },
            # 厨师端状态转换
            'chef': {
                'pending': ['confirmed', 'rejected'],
                'confirmed': ['preparing', 'cancelled'],
                'preparing': ['cooking'],
                'cooking': ['ready'],
                'ready': ['delivering'],
                'delivering': ['completed']
            },
            # 管理员状态转换
            'admin': {
                '*': ['cancelled', 'refunded']
            }
        }
        
        # 获取当前用户类型
        user_type = 'admin' if self.request.user.is_staff else self.request.user.user_type
        
        # 验证状态转换
        allowed_statuses = status_rules.get(user_type, {}).get(order.status, [])
        if user_type == 'admin' and '*' in status_rules['admin']:
            allowed_statuses += status_rules['admin']['*']
            
        if new_status not in allowed_statuses:
            raise serializers.ValidationError(
                f'无法从 {order.status} 状态变更为 {new_status} 状态'
            )
        
        order.change_status(
            to_status=new_status,
            changed_by=self.request.user,
            note=f"{user_type}状态变更: {order.status} → {new_status}"
        )

class ImageApprovalCheckView(APIView):
    """检查图片审核状态"""
    permission_classes = [permissions.IsAuthenticated]
    
    def get(self, request, image_url):
        # 从URL中提取图片路径
        image_path = image_url.split('/media/')[-1]
        full_path = os.path.join(settings.MEDIA_ROOT, image_path)
        
        # 检查菜品图片
        dish_image = DjDishImage.objects.filter(image=image_path).first()
        if dish_image:
            return Response({
                'approved': dish_image.is_approved,
                'type': 'dish'
            })
        
        # 检查厨师背景图
        chef = DjChef.objects.filter(background=image_path).first()
        if chef:
            return Response({
                'approved': chef.background_approved,
                'type': 'chef_background'
            })
        
        return Response({
            'approved': False,
            'type': 'unknown'
        }, status=status.HTTP_404_NOT_FOUND)

class ChefServiceOrderViewSet(viewsets.ModelViewSet):
    """厨师服务端订单视图集"""
    queryset = Order.objects.all()
    serializer_class = ChefServiceOrderItemSerializer
    permission_classes = [IsChefOwner]
    
    @action(detail=True, methods=['post'])
    def start_cooking(self, request, pk=None):
        """开始烹饪"""
        order = self.get_object()
        if order.status != 'confirmed':
            return Response(
                {'error': '只有已确认订单可以开始烹饪'},
                status=status.HTTP_400_BAD_REQUEST
            )
        
        order.change_status('preparing', request.user, '厨师开始烹饪')
        return Response({'status': 'preparing'})

class ChefServiceOrderStatusView(generics.ListAPIView):
    """
    厨师服务订单状态统计视图
    返回厨师不同状态订单的数量统计
    """
    serializer_class = OrderStatusCountSerializer
    permission_classes = [IsChefOwner]
    
    def get_queryset(self):
        chef = self.request.user.chef  # 假设用户已关联厨师
        return Order.objects.filter(chef=chef)
    
    def list(self, request, *args, **kwargs):
        queryset = self.get_queryset()
        
        # 统计各状态订单数量
        status_counts = {
            'pending': queryset.filter(status='pending').count(),
            'paid': queryset.filter(status='paid').count(),
            'preparing': queryset.filter(status='preparing').count(),
            'completed': queryset.filter(status='completed').count(),
            'cancelled': queryset.filter(status='cancelled').count(),
            'rejected': queryset.filter(status='rejected').count(),
        }
        
        return Response(status_counts)

# 厨师端后台
class VdjChefOrderViewSet(viewsets.ModelViewSet):
    """厨师服务端订单视图集"""
    queryset = Order.objects.all()
    serializer_class = ChefServiceOrderSerializer
    permission_classes = [IsChefOwner]
    filter_backends = [DjangoFilterBackend]
    filterset_fields = ['status', 'booked_time']
    ordering_fields = ['booked_time', 'created_at']
    
    def get_queryset(self):
        # 只返回当前厨师的订单
        return super().get_queryset().filter(
            chef__user=self.request.user
        ).select_related('customer', 'chef', 'address')
    
    @action(detail=True, methods=['post'])
    def accept(self, request, pk=None):
        """厨师接单"""
        order = self.get_object()
        if order.status != 'pending':
            return Response(
                {'error': '只有待确认订单可以接单'},
                status=status.HTTP_400_BAD_REQUEST
            )
        
        order.change_status('confirmed', request.user, '厨师已接单')
        return Response({'status': 'confirmed'})
    
    @action(detail=True, methods=['post'])
    def reject(self, request, pk=None):
        """厨师拒单"""
        order = self.get_object()
        if order.status != 'pending':
            return Response(
                {'error': '只有待确认订单可以拒绝'},
                status=status.HTTP_400_BAD_REQUEST
            )
        
        order.change_status('rejected', request.user, '厨师已拒绝')
        return Response({'status': 'rejected'})
    
    @action(detail=True, methods=['post'])
    def start(self, request, pk=None):
        """开始烹饪"""
        order = self.get_object()
        if order.status != 'confirmed':
            return Response(
                {'error': '只有已确认订单可以开始烹饪'},
                status=status.HTTP_400_BAD_REQUEST
            )
        
        order.change_status('preparing', request.user, '厨师开始烹饪')
        return Response({'status': 'preparing'})
    
    @action(detail=True, methods=['post'])
    def complete(self, request, pk=None):
        """完成订单"""
        order = self.get_object()
        if order.status != 'preparing':
            return Response(
                {'error': '只有准备中订单可以完成'},
                status=status.HTTP_400_BAD_REQUEST
            )
        
        order.change_status('completed', request.user, '厨师已完成订单')
        return Response({'status': 'completed'})

class VdjChefOrderStatsView(APIView):
    """厨师订单统计视图"""
    permission_classes = [IsChefOwner]
    
    def get(self, request):
        # 修正：厨师关联属性应为 chef（原代码错用 chef_profile）
        chef = request.user.chef
        today = timezone.now().date()
        
        stats = {
            'today_orders': Order.objects.filter(
                chef=chef,
                booked_time__date=today
            ).count(),
            'pending_orders': Order.objects.filter(
                chef=chef,
                status='pending'
            ).count(),
            'preparing_orders': Order.objects.filter(
                chef=chef,
                status='preparing'
            ).count(),
            'completed_orders': Order.objects.filter(
                chef=chef,
                status='completed'
            ).count(),
            'monthly_income': Order.objects.filter(
                chef=chef,
                status='completed',
                booked_time__month=today.month
            ).aggregate(Sum('total_amount'))['total_amount__sum'] or 0
        }
        
        return Response(stats)